package com.fxc.handler;

import com.fxc.MySQLRemoteService;
import com.fxc.RedisRemoteService;
import com.fxc.config.shortMailProperties;
import com.fxc.crowd.constant.CrowdConstant;
import com.fxc.crowd.util.CrowdUtil;
import com.fxc.crowd.util.ResultEntity;
import com.fxc.entity.PO.MemberPO;
import com.fxc.entity.VO.MemberLoginVO;
import com.fxc.entity.VO.MemberVO;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.annotation.Resource;
import javax.servlet.http.HttpSession;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * @author FXC
 * @version 1.0
 * @date 2021/12/7 8:45
 */
@Controller
public class MemberHandler {

    @Autowired
    private shortMailProperties mailProperties;

    @Autowired
    private MySQLRemoteService mySQLRemoteService;

    @Resource
    private RedisRemoteService remoteService;

    @RequestMapping("/auth/member/logout")
    public String logout(HttpSession session){

        session.invalidate();

        return "redirect:http://localhost:8081";
    }

    @RequestMapping("auth/member/do/login")
    public String toLogin(
            @RequestParam("loginAcct") String loginAcct,
            @RequestParam("userpswd") String userpswd,
            ModelMap modelMap,
            HttpSession session){

        // 调用远程接口根据登录账号查询MemberPO对象
        ResultEntity<MemberPO> resultEnitity = mySQLRemoteService.getMemberPOByLoginAcctRemote(loginAcct);

        if (ResultEntity.FAILED.equals(resultEnitity)){

            modelMap.addAttribute(CrowdConstant.ATTR_NAME_MESSAGE, resultEnitity.getMessage());

            return "member-login";
        }

        MemberPO memberPO = resultEnitity.getData();

        if (memberPO == null){

            modelMap.addAttribute(CrowdConstant.ATTR_NAME_MESSAGE, CrowdConstant.MESSAGE_LOGIN_FAILED);

            return "member-login";
        }

        // 比较密码
        String userpswdDataBase = memberPO.getUserpswd();

        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();

        boolean matchesResult = passwordEncoder.matches(userpswd, userpswdDataBase);

        if (!matchesResult){

            modelMap.addAttribute(CrowdConstant.ATTR_NAME_MESSAGE, CrowdConstant.MESSAGE_LOGIN_FAILED);

            return "member-login";
        }

        // 3.创建MemberLoginVO对象存入session域
        MemberLoginVO memberLoginVO = new MemberLoginVO(memberPO.getId(), memberPO.getUsername(), memberPO.getEmail());

        session.setAttribute(CrowdConstant.ATTR_NAME_LOGIN_MEMBER, memberLoginVO);

        return "redirect:http://localhost:8081/auth/member/to/center/page";
    }

    @RequestMapping("/auth/do/member/register")
    public String register(MemberVO memberVO, ModelMap modelMap){

        // 1.获取用户输入的手机号
        String phoneNum = memberVO.getPhoneNum();

        // 2.拼Redis中存储验证的key
        String key = CrowdConstant.REDIS_CODE_PREFIX + phoneNum;

        // 3.从redis读取key对应的Value
        ResultEntity<String> resultEntity = remoteService.getRedisStringValueByKeyRemote(key);

        // 4.检查查询操
        String result = resultEntity.getResult();

        if (ResultEntity.FAILED.equals(result)){

            modelMap.addAttribute(CrowdConstant.ATTR_NAME_MESSAGE, resultEntity.getMessage());

            return "member-reg";
        }
        String redisCode = resultEntity.getData();

        if (redisCode == null){

            modelMap.addAttribute(CrowdConstant.ATTR_NAME_MESSAGE, CrowdConstant.MESSAGE_CODE_NOT_EXISTS);

            return "member-reg";
        }

        // 5.作value比较表单验证码和Redis验证码
        String formCode = memberVO.getCode();

        if (!Objects.equals(formCode,redisCode)) {

            modelMap.addAttribute(CrowdConstant.ATTR_NAME_MESSAGE, CrowdConstant.MESSAGE_CODE_INVALID);

            return "member-reg";
        }

        // 6.如果验证码一致，则从Redis中删除
        remoteService.removeRedisKeyRemote(key);
        
        // 7.执行密码加密
        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        String userpswdFore = memberVO.getUserpswd();
        String encodeAfter = passwordEncoder.encode(userpswdFore);
        memberVO.setUserpswd(encodeAfter);

        // 8.执行保存
        // 8.1创建空MemberPO对象
        MemberPO memberPO = new MemberPO();

        // 8.2复制属性
        BeanUtils.copyProperties(memberVO, memberPO);

        // 8.3调用远程方法
        ResultEntity<String> saveMemberResultEntity = mySQLRemoteService.saveMember(memberPO);

        if (ResultEntity.FAILED.equals(saveMemberResultEntity)){

            modelMap.addAttribute(CrowdConstant.ATTR_NAME_MESSAGE, saveMemberResultEntity.getMessage());

            return "member-reg";
        }

        // 使用重定向避免刷新浏览器导致重新执行注册流程
        return "redirect:/auth/member/to/login/page";
    }

    @ResponseBody
    @RequestMapping("/auth/member/send/short/message.json")
    public ResultEntity<String> sendMail(@RequestParam("phoneNum") String phoneNum){

        // 1.发送验证码到phoneNum邮箱
        ResultEntity<String> sendMessageEntity = CrowdUtil.sendShortMail(mailProperties.getTitle(),
                mailProperties.getSignature(),
                mailProperties.getAppCode(),
                mailProperties.getAccount(),
                phoneNum);

        // 2.判断邮箱发送结果
        if (ResultEntity.SUCCESS.equals(sendMessageEntity.getResult())){

            // 3.如果发送成功将验证码存入Redis
            // 3.1 从上一步操作结果中获取随机验证码
            String code = sendMessageEntity.getData();

            // 3.2拼接一个用于在Reids中数据储存的KEY
            String key = CrowdConstant.REDIS_CODE_PREFIX + phoneNum;

            // 判断结果
            ResultEntity<String> saveCodeResultEntity = remoteService.setRedisKeyValueRemoteWithTimeOut(key,code,15, TimeUnit.MINUTES);

            if (ResultEntity.SUCCESS.equals(saveCodeResultEntity.getResult())){
                return ResultEntity.successWithData("");
            }else {
                return saveCodeResultEntity;
            }
        }else {
            return sendMessageEntity;
        }
    }
}
